package com.aiti.lulian.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.aiti.base.core.base.service.iml.BaseSerivceImpl;
import com.aiti.base.core.exception.BusinessException;
import com.aiti.base.core.utils.encrypt.Md5Util;
import com.aiti.base.core.utils.message.Message;
import com.aiti.base.core.utils.uuid.UUIDUtil;
import com.aiti.framework.commons.dictmodel.entity.SysDictData;
import com.aiti.framework.commons.dictmodel.mapper.SysDictDataMapper;
import com.aiti.lulian.constant.GxmhConstant;
import com.aiti.lulian.dto.gonxin.FundDto;
import com.aiti.lulian.entity.Bank;
import com.aiti.lulian.entity.Fund;
import com.aiti.lulian.entity.FundApplication;
import com.aiti.lulian.entity.MyCollection;
import com.aiti.lulian.entity.excel.FundImport;
import com.aiti.lulian.gxmh.dto.SubUser;
import com.aiti.lulian.gxmh.dto.SysUserDto;
import com.aiti.lulian.gxmh.entity.GxmhServerFund;
import com.aiti.lulian.gxmh.service.GxmhServerFundService;
import com.aiti.lulian.mapper.gongxin.BankMapper;
import com.aiti.lulian.mapper.gongxin.FundApplicationMapper;
import com.aiti.lulian.mapper.gongxin.FundMapper;
import com.aiti.lulian.mapper.gxmh.GxmhSysMapper;
import com.aiti.lulian.service.IFundService;
import com.aiti.lulian.service.IMyCollectionService;
import com.aiti.lulian.vo.gongxin.FundVo;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class FundServiceImpl extends BaseSerivceImpl<FundMapper, Fund> implements IFundService {

    @Autowired
    private FundMapper fundMapper;

    @Autowired
    private BankMapper bankMapper;

    @Autowired
    private FundApplicationMapper fundApplicationMapper;

    @Autowired
    private SysDictDataMapper sysDictDataMapper;

    @Autowired
    private IMyCollectionService myCollectionService;

    @Autowired
    private GxmhSysMapper gxmhSysMapper;
    @Autowired
    private GxmhServerFundService gxmhServerFundService;

    /**
     * 添加资金产品
     * @param dto
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addFund(FundDto dto) {
        Fund fund = new Fund();
        BeanUtils.copyProperties(dto, fund);
        String productType = String.join(",", dto.getProductTypeList());
        fund.setProductType(productType);
        String fundTag = String.join(",", dto.getFundTagList());
        fund.setFundTag(fundTag);
        fund.setCreator(dto.getUserId());
        fund.setBaseCreateTime(new Date());
        fund.setBaseUpdateTime(new Date());
        this.save(fund);
        if(StrUtil.isNotBlank(dto.getIsCreateServiceUser()) && "1".equals(dto.getIsCreateServiceUser())) {
            SubUser subUser = this.createServerUser(dto);
            GxmhServerFund gxmhServerFund = this.getGxmhServerFund(dto, subUser, fund);
            gxmhServerFundService.save(gxmhServerFund);
        }
    }

    private GxmhServerFund getGxmhServerFund(FundDto dto, SubUser subUser, Fund fund) {
        GxmhServerFund gxmhServerFund = new GxmhServerFund();
        gxmhServerFund.setBaseId(UUIDUtil.getUUID2());
        gxmhServerFund.setUserId(subUser.getBaseId());
        gxmhServerFund.setFundId(fund.getBaseId());
        gxmhServerFund.setBaseCreateBy(dto.getUserId());
        gxmhServerFund.setBaseUpdateBy(dto.getUserId());
        gxmhServerFund.setIsDelete(0);
        gxmhServerFund.setBaseCreateTime(new Date());
        gxmhServerFund.setBaseUpdateTime(new Date());
        return gxmhServerFund;
    }

    /**
     * 创建产品服务商用户
     * @param dto
     */
    private SubUser createServerUser(FundDto dto) {
        if(StrUtil.isBlank(dto.getUsername()) && StrUtil.isBlank(dto.getPassword())) {
            throw new BusinessException("请填写用户名和密码");
        }
        // 判断用户是否存在
        String existUserId = gxmhSysMapper.queryUserIdByUsername(dto.getUsername());
        if(StrUtil.isNotEmpty(existUserId)) {
            throw new BusinessException("用户【"+dto.getUsername()+"】已存在，请联系管理员处理");
        }
        // 创建用户和角色绑定
        SubUser subUser = buildSubUser(dto);
        gxmhSysMapper.insertServerUser(subUser);
        gxmhSysMapper.insertUserRole(UUIDUtil.getUUID2(), subUser.getBaseId(), GxmhConstant.CHAN_PIN_SERVER_ROLE_ID);
        return subUser;
    }

    private SubUser buildSubUser(FundDto dto) {
        String username = dto.getUsername();
        String password = dto.getPassword();
        Bank bank = bankMapper.selectById(dto.getBankId());
        if(bank == null) {
            throw new BusinessException("银行不存在");
        }
        SubUser subUser = new SubUser();
        subUser.setBaseId(UUIDUtil.getUUID2());
        subUser.setUsername(username);
        subUser.setMobile(username);
        subUser.setIsMain(true);
        subUser.setIsSignin("1");
        subUser.setIsDelete(false);
        subUser.setSource(GxmhConstant.GXMH_SERVER_USER_FLAG);
        subUser.setBaseCreateTime(new Date());
        subUser.setBaseUpdateTime(new Date());
        subUser.setProvince(GxmhConstant.SHAN_DONG_PROVINCE);
        subUser.setCity(bank.getCity());
        subUser.setRegion(bank.getCounty());
        subUser.setStreet(bank.getStreet());
        subUser.setBackgroundId("a5ed9caf3b1960e6b3b43bb6c1ffbddc");
        subUser.setSelectedTemplateId("a5ed9caf3b1960e6b3b43bb6c1ffbddc");
        subUser.setYmm(StrUtil.isNotBlank(subUser.getPassword()) ? password : username);
        String password1 = Md5Util.hash(password);
        subUser.setPassword(password1);
        return subUser;
    }

    @Override
    public List<FundVo> getList(Page<FundVo> page, FundDto dto) {
        SysUserDto sysUserDto = gxmhSysMapper.queryUserInfo(dto.getUserId());
        if(sysUserDto == null) {
            throw new BusinessException("用户不存在");
        }
        // 如果当前用户是服务商用户，则只能查看跟服务商相关的产品数据。目前一个服务商用户只有一条商品数据
        if(GxmhConstant.GXMH_SERVER_USER_FLAG.equals(sysUserDto.getSource())) {
            return fundMapper.selectServerUserFundList(page, dto);
        }

        return fundMapper.selectFundList(page, dto);
    }

    @Override
    public FundVo getDetails(String baseId, String userId) {
        FundVo fundVo = fundMapper.selectDetails(baseId);
        List<String> productTypeList = Arrays.asList(fundVo.getProductType().split(","));
        fundVo.setProductTypeList(productTypeList);
        if(StrUtil.isEmpty(userId)) {
            return fundVo;
        }
        // 查询该商品绑定的用户
        LambdaQueryWrapper<GxmhServerFund> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(GxmhServerFund::getFundId, baseId).eq(GxmhServerFund::getIsDelete, 0);
        GxmhServerFund serverFund = gxmhServerFundService.getOne(queryWrapper);
        if(serverFund != null) {
            SysUserDto sysUserDto = gxmhSysMapper.queryUserInfo(serverFund.getUserId());
            fundVo.setServerUsername(sysUserDto.getUsername());
            fundVo.setServerUserExistFlag(true);
            // 如果这个服务用户是当前登录用户创建的，则设置删除标识
            if(userId.equals(serverFund.getBaseCreateBy())) {
                fundVo.setDelServerUserFlag(1);
            }
        }
        return fundVo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteServerUser(String username, String fundBaseId) {
        String userId = gxmhSysMapper.queryUserIdByUsername(username);
        if(StrUtil.isNotEmpty(userId)) {
            // 删除用户角色和用户数据
            gxmhSysMapper.deleteUserRoleByUserId(userId);
            gxmhSysMapper.deleteUserByUsername(username);
        }
        // 删除绑定数据
        gxmhServerFundService.remove(new LambdaQueryWrapper<GxmhServerFund>()
                 .eq(GxmhServerFund::getUserId, userId)
                 .eq(GxmhServerFund::getFundId, fundBaseId)
                 .eq(GxmhServerFund::getIsDelete, 0));
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateFund(FundDto dto) {
        Fund fund = new Fund();
        BeanUtils.copyProperties(dto, fund);
        String productType = String.join(",", dto.getProductTypeList());
        fund.setProductType(productType);
        String fundTag = String.join(",", dto.getFundTagList());
        fund.setFundTag(fundTag);
        fund.setUpdateBy(dto.getUserId());
        fund.setBaseUpdateTime(new Date());
        this.updateById(fund);
        // 更新收藏表
        List<MyCollection> collections = myCollectionService.list(new LambdaQueryWrapper<MyCollection>().eq(MyCollection::getModule, "3").eq(MyCollection::getId, dto.getBaseId()));
        List<String> collectionIds = collections.stream().map(MyCollection::getBaseId).collect(Collectors.toList());
        if (collections.size() > 0) {
            myCollectionService.update(new LambdaUpdateWrapper<MyCollection>().in(MyCollection::getBaseId, collectionIds).set(MyCollection::getType, dto.getProductType()));
        }
        // 创建服务用户
        if(StrUtil.isNotBlank(dto.getIsCreateServiceUser()) && "1".equals(dto.getIsCreateServiceUser())) {
            SubUser subUser = this.createServerUser(dto);
            GxmhServerFund gxmhServerFund = this.getGxmhServerFund(dto, subUser, fund);
            gxmhServerFundService.save(gxmhServerFund);
        }
    }

    @Override
    public Message deleteFund(FundDto dto) {
        List<FundApplication> fundApplications = fundApplicationMapper.selectList(new LambdaQueryWrapper<FundApplication>().eq(FundApplication::getFundId, dto.getBaseId()));
        if (fundApplications.size() > 0) {
            return Message.fail("该产品存在申请，删除失败");
        }
        fundMapper.deleteById(dto.getBaseId());
        // 删除该产品绑定的服务商数据
        List<GxmhServerFund> serverFundList = gxmhServerFundService.list(new LambdaQueryWrapper<GxmhServerFund>().eq(GxmhServerFund::getFundId, dto.getBaseId()).eq(GxmhServerFund::getIsDelete, 0));
        if(CollectionUtil.isNotEmpty(serverFundList)) {
            for(GxmhServerFund serverFund : serverFundList) {
                // 删除用户角色和用户数据
                gxmhSysMapper.deleteUserRoleByUserId(serverFund.getUserId());
                gxmhSysMapper.deleteUserByUserId(serverFund.getUserId());
            }
            gxmhServerFundService.remove(new LambdaQueryWrapper<GxmhServerFund>().eq(GxmhServerFund::getFundId, dto.getBaseId()));
        }
        return Message.success("删除成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Message importBatch(MultipartFile file, String userId) throws IOException {
        // 构建报错信息集
        List<String> msgList = new ArrayList<>();
        // 读取数据
        List<FundImport> fundImportList = EasyExcel.read(file.getInputStream()).head(FundImport.class).headRowNumber(1).sheet("资金产品").doReadSync();
        if (fundImportList == null) {
            return Message.fail("请正确上传文件");
        }
        if (fundImportList != null && fundImportList.size() == 0) {
            return Message.fail("尚未读取到数据");
        }
        List<Fund> funds = new ArrayList<>();
        for (FundImport fundImport : fundImportList) {
            String bankName = fundImport.getBankName();
            if (StrUtil.isBlank(bankName)) {
                msgList.add("第" + (fundImportList.indexOf(fundImport) + 1) + "条：银行名称不能为空<br/>");
                continue;
            }
            if (StrUtil.isBlank(fundImport.getFundName())) {
                msgList.add("第" + (fundImportList.indexOf(fundImport) + 1) + "条：产品名称不能为空<br/>");
                continue;
            }
            if (StrUtil.isBlank(fundImport.getProductType())) {
                msgList.add("第" + (fundImportList.indexOf(fundImport) + 1) + "条：产品类型不能为空<br/>");
                continue;
            }
            if (StrUtil.isBlank(fundImport.getFundType())) {
                msgList.add("第" + (fundImportList.indexOf(fundImport) + 1) + "条：资源类型不能为空<br/>");
                continue;
            }
            if (StrUtil.isBlank(fundImport.getLoanAmount())) {
                msgList.add("第" + (fundImportList.indexOf(fundImport) + 1) + "条：贷款额度不能为空<br/>");
                continue;
            }
            if (StrUtil.isBlank(fundImport.getLoanTerm())) {
                msgList.add("第" + (fundImportList.indexOf(fundImport) + 1) + "条：贷款期限不能为空<br/>");
                continue;
            }
            if (StrUtil.isBlank(fundImport.getRecent3mAnnualizedRate())) {
                msgList.add("第" + (fundImportList.indexOf(fundImport) + 1) + "条：近三月年化率不能为空<br/>");
                continue;
            }
            if (StrUtil.isBlank(fundImport.getProductDescription())) {
                msgList.add("第" + (fundImportList.indexOf(fundImport) + 1) + "条：产品说明不能为空<br/>");
                continue;
            }
            Fund fund = new Fund();
            fund.setFundName(fundImport.getFundName());
            StringBuilder sb = new StringBuilder();
            if (fundImport.getProductType().contains("信用类产品")) {
                sb.append("信用类产品,");
            }
            if (fundImport.getProductType().contains("担保类产品")) {
                sb.append("担保类产品,");
            }
            if (fundImport.getProductType().contains("抵押类产品")) {
                sb.append("抵押类产品,");
            }
            String productType = sb.toString();
            productType = productType.replaceAll("^,|,$", "");
            if (productType.length() == 0) {
                msgList.add("第" + (fundImportList.indexOf(fundImport) + 1) + "条：产品类型填写错误<br/>");
            }
            fund.setProductType(productType);
            fund.setFundTag(productType);

            SysDictData fundTypeDict = sysDictDataMapper.selectOne(new LambdaQueryWrapper<SysDictData>().eq(SysDictData::getBaseName, fundImport.getFundType()).eq(SysDictData::getDictTypeNo, "GONGXIN_FUND_RESOURCE_TYPE").eq(SysDictData::getIsDelete, false));
            if (fundTypeDict == null) {
                msgList.add("第" + (fundImportList.indexOf(fundImport) + 1) + "条：资源类型填写错误<br/>");
                continue;
            } else {
                fund.setFundType(fundTypeDict.getBaseId());
            }
            if (StrUtil.equals("30万以下", fundImport.getLoanAmount())) {
                fund.setLoanAmount(1);
            } else if (StrUtil.equals("30-50万元", fundImport.getLoanAmount())) {
                fund.setLoanAmount(2);
            } else if (StrUtil.equals("50-100万元", fundImport.getLoanAmount())) {
                fund.setLoanAmount(3);
            } else if (StrUtil.equals("100-300万元", fundImport.getLoanAmount())) {
                fund.setLoanAmount(4);
            } else if (StrUtil.equals("300-500万元", fundImport.getLoanAmount())) {
                fund.setLoanAmount(5);
            } else if (StrUtil.equals("500-1000万元", fundImport.getLoanAmount())) {
                fund.setLoanAmount(6);
            } else if (StrUtil.equals("1000万元以上", fundImport.getLoanAmount())) {
                fund.setLoanAmount(7);
            } else {
                msgList.add("第" + (fundImportList.indexOf(fundImport) + 1) + "条：贷款额度填写错误<br/>");
                continue;
            }
            if (StrUtil.equals("12个月", fundImport.getLoanTerm())) {
                fund.setLoanTerm(1);
            } else if (StrUtil.equals("24个月", fundImport.getLoanTerm())) {
                fund.setLoanTerm(2);
            } else if (StrUtil.equals("36个月", fundImport.getLoanTerm())) {
                fund.setLoanTerm(3);
            } else if (StrUtil.equals("36个月以上", fundImport.getLoanTerm())) {
                fund.setLoanTerm(4);
            } else {
                msgList.add("第" + (fundImportList.indexOf(fundImport) + 1) + "条：贷款期限填写错误<br/>");
                continue;
            }
            Bank bank = bankMapper.selectOne(new LambdaQueryWrapper<Bank>().eq(Bank::getBaseName, fundImport.getBankName()));
            if (bank == null) {
                msgList.add("第" + (fundImportList.indexOf(fundImport) + 1) + "条：银行名称尚未查询到<br/>");
                continue;
            } else {
                fund.setBankId(bank.getBaseId());
            }
            String recent3mAnnualizedRateStr = fundImport.getRecent3mAnnualizedRate();
//            if (! recent3mAnnualizedRateStr.matches("^\\d+(\\.\\d+)?$")) {
//                msgList.add("第" + (fundImportList.indexOf(fundImport) + 1) + "条：近三月年化率填写错误<br/>");
//                continue;
//            }
//            Double recent3mAnnualizedRate = Double.valueOf(recent3mAnnualizedRateStr);
//            if (recent3mAnnualizedRate > 100 || recent3mAnnualizedRate <= 0) {
//                msgList.add("第" + (fundImportList.indexOf(fundImport) + 1) + "条：近三月年化率填写错误<br/>");
//                continue;
//            }
            fund.setRecent3mAnnualizedRate(recent3mAnnualizedRateStr);
            fund.setProductDescription(fundImport.getProductDescription());
            fund.setCreator(userId);
            fund.setBaseCreateTime(new Date());
            fund.setBaseUpdateTime(new Date());
            fund.setLoanAmountStr(fundImport.getLoanAmountStr());
            fund.setLoanTermStr(fundImport.getLoanTermStr());
            funds.add(fund);
        }
        if (funds.size() > 0) {
            this.saveBatch(funds);
        }
        if (msgList.size() > 0) {
            return Message.fail("以下数据导入失败：<br/>" + msgList.stream().collect(Collectors.joining("")));
        } else {
            return Message.success("导入成功");
        }
    }
}
